package mop.gui.reservation;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.swing.DefaultListModel;
import mop.controller.MakeResourceReservationController;
import mop.gui.GUI;
import mop.model.resource.ReservationInterface;
import mop.model.resource.ResourceInterface;
import mop.model.task.TaskInterface;

/**
 * MakeReservationDialog
 * 
 * @author  MOP Team 7
 */
public class MakeReservationDialog extends javax.swing.JDialog 
{
    /**
     * Constructor.
     *
     * @param   gui
     * @param   makeResourceReservationController
     * @param   task
     */
    public MakeReservationDialog(GUI gui, MakeResourceReservationController makeResourceReservationController, TaskInterface task)
    {
        super(gui.getMainWindow(), true);
        initComponents();
        
        setGui(gui);
        this.makeResourceReservationController = makeResourceReservationController;

        // Set task
        this.task = task;
        this.lblTask.setText(task.getId());

        // Load resources
        this.resources = makeResourceReservationController.getResourceList();
        for (ResourceInterface r : this.resources)
            this.cmbResource.addItem(r.getId());

        loadReservations();
    }
    
    /***************************************************************************
     *                          GUI reference
     ***************************************************************************/
    
    private GUI gui;
    
    /**
     * Sets the GUI.
     * 
     * @param   gui
     * @post    gui is set.
     */
    private void setGui(GUI gui)
    {
        this.gui = gui;
    }
    
    /**
     * Returns the GUI reference.
     * 
     * @return  this.gui
     */
    public GUI getGui()
    {
        return this.gui;
    }
    
    /***************************************************************************
     *                          Controllers
     ***************************************************************************/
    
    private MakeResourceReservationController makeResourceReservationController;
    
    /***************************************************************************
     *                          Selected task
     ***************************************************************************/
    
    private TaskInterface task;

    /***************************************************************************
     *                         Resource List
     ***************************************************************************/

    private List<ResourceInterface> resources;

    /***************************************************************************
     *                          Dialog-specific functionality
     ***************************************************************************/
    
    /**
     * Loads the reservations list.
     */
    private void loadReservations()
    {
        int index = this.cmbResource.getSelectedIndex();

        if (index >= 0 && index < resources.size())
        {
            try
            {
                LinkedList<ReservationInterface> reservations = (LinkedList<ReservationInterface>) resources.get(index).getReservationsList();

                DefaultListModel model = new DefaultListModel();
                for(ReservationInterface r : reservations)
                    model.addElement(r.toString());

                this.listReservations.setModel(model);
            }
            catch (Throwable exception)
            {
                // cannot load reservation list!
                gui.handleError(exception);
                this.dispose();
            }
        }
    }
    
    private DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);

    /**
     * Validate and set the datetime field on the screen given a datetime string.
     * @param dateTime The datetime string
     */
    public void setStartDateTime(String dateTimeString)
    {
        Date dateTime = null;
        try
        {
            if ((dateTimeString != null) && (dateTimeString.length() > 0))
                dateTime = dateTimeFormat.parse(dateTimeString);
	}
        catch (Exception e)
        {
            dateTime = null;
        }
        this.setStartDateTime(dateTime);
    }

    /**
     * Returns the start date & time as a Date object.
     *
     * @return  start as Date object
     */
    public Date getStartDateTime()
    {
        Date dateTime = null;
        String dateTimeString = txtStart.getText();

        try
        {
            if ((dateTimeString != null) && (dateTimeString.length() > 0))
                dateTime = dateTimeFormat.parse(dateTimeString);
	}
        catch (Exception e)
        {
            dateTime = null;
        }

        return dateTime;
    }

    /**
     * Validate and set the datetime field on the screen given a date.
     * @param dateTime The datetime object
     */
    public void setStartDateTime(Date dateTime)
    {
        String dateTimeString = "";
        if (dateTime != null)
            dateTimeString = dateTimeFormat.format(dateTime);
        txtStart.setText(dateTimeString);
        btnStartDate.setTargetDate(dateTime);
        btnStartTime.setTargetDate(dateTime);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lblMakeReservation = new javax.swing.JLabel();
        lblResource = new javax.swing.JLabel();
        btnMakeReservation = new javax.swing.JButton();
        btnCancel = new javax.swing.JButton();
        lblReservations = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        listReservations = new javax.swing.JList();
        lblStart = new javax.swing.JLabel();
        txtStart = new javax.swing.JTextField();
        txtWeeks = new javax.swing.JTextField();
        lblWeeks = new javax.swing.JLabel();
        lblDays = new javax.swing.JLabel();
        txtDays = new javax.swing.JTextField();
        lblHours = new javax.swing.JLabel();
        lblMinutes = new javax.swing.JLabel();
        txtHours = new javax.swing.JTextField();
        txtMinutes = new javax.swing.JTextField();
        btnStartDate = new org.sourceforge.jcalendarbutton.JCalendarButton();
        btnStartTime = new net.sourceforge.jcalendarbutton.JTimeButton();
        lblTask = new javax.swing.JLabel();
        cmbResource = new javax.swing.JComboBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Make Reservation");

        lblMakeReservation.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        lblMakeReservation.setText("Make Reservation For Task ");
        lblMakeReservation.setName("lblMakeReservation"); // NOI18N

        lblResource.setText("Select a Resource");
        lblResource.setName("lblResource"); // NOI18N

        btnMakeReservation.setText("Make Reservation");
        btnMakeReservation.setName("btnMakeReservation"); // NOI18N
        btnMakeReservation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnMakeReservationActionPerformed(evt);
            }
        });

        btnCancel.setText("Cancel");
        btnCancel.setName("btnCancel"); // NOI18N
        btnCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCancelActionPerformed(evt);
            }
        });

        lblReservations.setText("Existing Reservations");
        lblReservations.setName("lblReservations"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        listReservations.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        listReservations.setEnabled(false);
        listReservations.setName("listReservations"); // NOI18N
        jScrollPane2.setViewportView(listReservations);

        lblStart.setText("Start date and time");
        lblStart.setName("lblStart"); // NOI18N

        txtStart.setEditable(false);
        txtStart.setName("txtStart"); // NOI18N
        txtStart.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtStartFocus(evt);
            }
        });

        txtWeeks.setText("0");
        txtWeeks.setName("txtWeeks"); // NOI18N

        lblWeeks.setText("Duration - Weeks");
        lblWeeks.setName("lblWeeks"); // NOI18N

        lblDays.setText("Days");
        lblDays.setName("lblDays"); // NOI18N

        txtDays.setText("0");
        txtDays.setName("txtDays"); // NOI18N

        lblHours.setText("Hours");
        lblHours.setName("lblHours"); // NOI18N

        lblMinutes.setText("Minutes");
        lblMinutes.setName("lblMinutes"); // NOI18N

        txtHours.setText("0");
        txtHours.setName("txtHours"); // NOI18N

        txtMinutes.setText("0");
        txtMinutes.setName("txtMinutes"); // NOI18N

        btnStartDate.setName("btnStartDate"); // NOI18N
        btnStartDate.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                startChange(evt);
            }
        });

        btnStartTime.setName("btnStartTime"); // NOI18N
        btnStartTime.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                startChange(evt);
            }
        });

        lblTask.setFont(new java.awt.Font("Tahoma", 3, 12)); // NOI18N
        lblTask.setName("lblTask"); // NOI18N

        cmbResource.setName("cmbResource"); // NOI18N
        cmbResource.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmbResourceActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cmbResource, 0, 369, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(lblMakeReservation)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblTask))
                    .addComponent(lblResource)
                    .addComponent(lblReservations)
                    .addComponent(lblStart)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(txtStart, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnStartDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 369, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(txtHours)
                            .addComponent(txtWeeks, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE)
                            .addComponent(lblWeeks)
                            .addComponent(lblHours)
                            .addComponent(btnMakeReservation, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(lblMinutes)
                            .addComponent(lblDays)
                            .addComponent(txtDays, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
                            .addComponent(txtMinutes, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
                            .addComponent(btnCancel, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblMakeReservation)
                    .addComponent(lblTask))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblResource)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cmbResource, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblReservations)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblStart)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(btnStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtStart, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(lblWeeks)
                            .addComponent(lblDays, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtWeeks, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtDays, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(lblHours)
                            .addComponent(lblMinutes))
                        .addGap(13, 13, 13)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtHours, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(btnCancel)
                            .addComponent(btnMakeReservation)))
                    .addComponent(btnStartDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Makes a reservation.
     * 
     * @param   evt
     */
    private void btnMakeReservationActionPerformed(java.awt.event.ActionEvent evt)
    {
        // Check resource
        int index = this.cmbResource.getSelectedIndex();
        if (index < 0 || index > resources.size())
        {
            gui.handleError("Please select a resource first!");
            return;
        }
        ResourceInterface resource = resources.get(index);

        // Parse start time/date.
        Timestamp start = new Timestamp(this.getStartDateTime().getTime());

        // Load duration.
        long ms = 0;
        ms += Long.parseLong(this.txtMinutes.getText()) * 60000; // 1 minute = 60k ms
        ms += Long.parseLong(this.txtHours.getText()) * 3600000; // 1 hour = 3.6m ms
        ms += Long.parseLong(this.txtDays.getText()) * 86400000; // 1 day = 86.4m ms
        ms += Long.parseLong(this.txtWeeks.getText()) * 604800000; // 1 week = 604.8m ms
        Timestamp duration = new Timestamp(ms);

        // Add the reservation.
        try {
            makeResourceReservationController.makeReservation(task.getId(), resource.getId(), start, duration);
            gui.handleSuccess("Reservation made!");
            gui.getMainWindow().update();
            this.dispose();
        } catch (Throwable exception) {
            gui.handleError(exception);
        }
    }

/**
 * Closes the dialog.
 * 
 * @param   evt
 */
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
    this.dispose();
}//GEN-LAST:event_btnCancelActionPerformed

private void txtStartFocus(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtStartFocus
    setStartDateTime(txtStart.getText());
}//GEN-LAST:event_txtStartFocus

private void startChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_startChange
    if (evt.getNewValue() instanceof Date)
        setStartDateTime((Date)evt.getNewValue());
}//GEN-LAST:event_startChange

private void cmbResourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbResourceActionPerformed
    if (this.cmbResource.getSelectedIndex() >= 0 && this.cmbResource.getSelectedIndex() < resources.size())
        this.loadReservations();
}//GEN-LAST:event_cmbResourceActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCancel;
    private javax.swing.JButton btnMakeReservation;
    private org.sourceforge.jcalendarbutton.JCalendarButton btnStartDate;
    private net.sourceforge.jcalendarbutton.JTimeButton btnStartTime;
    private javax.swing.JComboBox cmbResource;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lblDays;
    private javax.swing.JLabel lblHours;
    private javax.swing.JLabel lblMakeReservation;
    private javax.swing.JLabel lblMinutes;
    private javax.swing.JLabel lblReservations;
    private javax.swing.JLabel lblResource;
    private javax.swing.JLabel lblStart;
    private javax.swing.JLabel lblTask;
    private javax.swing.JLabel lblWeeks;
    private javax.swing.JList listReservations;
    private javax.swing.JTextField txtDays;
    private javax.swing.JTextField txtHours;
    private javax.swing.JTextField txtMinutes;
    private javax.swing.JTextField txtStart;
    private javax.swing.JTextField txtWeeks;
    // End of variables declaration//GEN-END:variables
}